package com.rrd.hive.udf;

import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.io.Text;

import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Description(
        name = "xml_format",
        value = "_FUNC_(text) - format string to xml string by the xml rules",
        extended = "Example:\n> SELECT _FUNC_('<a>1</a><123a>2</123a><1:a>3</1:a><_a>4</_a><xmla>5</xmla><a b>5</a b>');\n  <a>1</a><n123a>2</n123a><n12a>3</n12a><n_a>4</n_a><nxmla>5</nxmla><a_b>5</a_b>"
)
public class XmlFormatUDF extends UDF {
    Pattern pattern = Pattern.compile("(?is)(\\<\\/?)([^\\>]+)(\\>)");
    private Text result = new Text();

    public Text evaluate(String xml) {
        if (xml == null) {
            return null;
        }
        Matcher m = pattern.matcher(xml);
        StringBuffer sb = new StringBuffer();
        HashMap<String, Integer> map = new HashMap<>();
        while (m.find()) {
            try {
                String field = m.group(2);
                Integer count = map.get(field);
                if (count == null) {
                    count = 0;
                }
                map.put(field, count + 1);
                String newField = field.replace(" ", "_").replace(":", "2").replaceAll("(?is)^(\\d+|xml|\\_)", "n$1");
                m.appendReplacement(sb, m.group(1) + newField + m.group(3));
            } catch (IndexOutOfBoundsException ex) {
                ex.printStackTrace();
            }
        }
        m.appendTail(sb);
        String r = sb.toString();
        for (String k : map.keySet()) {
            Integer v = map.get(k);
            if (v.equals(1)){
                r = r.replace("<" + k + ">", "").replace("</" + k + ">", "");
            }
        }
        result.set(r);
        return result;
    }

    public static void main(String[] args) {
        String a = "<a>1</a><123a>2</123a><1:a>3</1:a><_a>4</_a><xmla>5</xmla><a b>5</a b><abc><bcd></ccc><bcd/>";
        Text a1 = new XmlFormatUDF().evaluate(a);
        System.out.println(a1);
    }
}